//
//  BMSRealnameValidator.m
//  WDBMS
//
//  Created by YeJary on 2025/5/27.
//

#import "BMSRealnameValidator.h"

#pragma mark - BMSValidationResult Implementation

@interface BMSValidationResult ()
@property (nonatomic, assign, readwrite) BOOL isValid;
@property (nonatomic, copy, readwrite, nullable) NSString *errorMessage;
@end

@implementation BMSValidationResult

+ (instancetype)successResult {
    BMSValidationResult *result = [[BMSValidationResult alloc] init];
    result.isValid = YES;
    result.errorMessage = nil;
    return result;
}

+ (instancetype)failureResultWithMessage:(NSString *)message {
    BMSValidationResult *result = [[BMSValidationResult alloc] init];
    result.isValid = NO;
    result.errorMessage = message;
    return result;
}

@end

#pragma mark - BMSRealnameValidationResult Implementation

@interface BMSRealnameValidationResult ()
@property (nonatomic, assign, readwrite) BOOL isValid;
@property (nonatomic, copy, readwrite, nullable) NSString *nameError;
@property (nonatomic, copy, readwrite, nullable) NSString *idCardError;
@end

@implementation BMSRealnameValidationResult

+ (instancetype)successResult {
    BMSRealnameValidationResult *result = [[BMSRealnameValidationResult alloc] init];
    result.isValid = YES;
    result.nameError = nil;
    result.idCardError = nil;
    return result;
}

+ (instancetype)failureResultWithNameError:(nullable NSString *)nameError
                               idCardError:(nullable NSString *)idCardError {
    BMSRealnameValidationResult *result = [[BMSRealnameValidationResult alloc] init];
    result.isValid = NO;
    result.nameError = nameError;
    result.idCardError = idCardError;
    return result;
}

@end

#pragma mark - BMSRealnameValidator Implementation

@implementation BMSRealnameValidator

#pragma mark - 单项验证方法

- (BMSValidationResult *)validateName:(NSString *)name {
    // 空值检查
    if (!name || name.length == 0) {
        return [BMSValidationResult failureResultWithMessage:@"请输入真实姓名"];
    }
    
    // 去除首尾空格
    NSString *trimmedName = [name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if (trimmedName.length == 0) {
        return [BMSValidationResult failureResultWithMessage:@"请输入真实姓名"];
    }
    
    // 长度检查
    if (trimmedName.length < 2) {
        return [BMSValidationResult failureResultWithMessage:@"姓名至少需要2个字符"];
    }
    
    if (trimmedName.length > 10) {
        return [BMSValidationResult failureResultWithMessage:@"姓名不能超过10个字符"];
    }
    
    // 中文姓名格式检查
    if (![self isValidChineseName:trimmedName]) {
        return [BMSValidationResult failureResultWithMessage:@"请输入正确的中文姓名"];
    }
    
    return [BMSValidationResult successResult];
}

- (BMSValidationResult *)validateIDCard:(NSString *)idCard {
    // 空值检查
    if (!idCard || idCard.length == 0) {
        return [BMSValidationResult failureResultWithMessage:@"请输入身份证号"];
    }
    
    // 去除首尾空格
    NSString *trimmedID = [idCard stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    if (trimmedID.length == 0) {
        return [BMSValidationResult failureResultWithMessage:@"请输入身份证号"];
    }
    
    // 长度检查
    if (trimmedID.length != 18) {
        return [BMSValidationResult failureResultWithMessage:@"身份证号必须为18位"];
    }
    
    // 格式检查
    if (![self isValidIDCardNumber:trimmedID]) {
        return [BMSValidationResult failureResultWithMessage:@"身份证号格式错误"];
    }
    
    return [BMSValidationResult successResult];
}

#pragma mark - 组合验证方法

- (BMSRealnameValidationResult *)validateRealnameWithName:(NSString *)name
                                                   idCard:(NSString *)idCard {
    BMSValidationResult *nameResult = [self validateName:name];
    BMSValidationResult *idResult = [self validateIDCard:idCard];
    
    if (nameResult.isValid && idResult.isValid) {
        return [BMSRealnameValidationResult successResult];
    }
    
    return [BMSRealnameValidationResult failureResultWithNameError:nameResult.errorMessage
                                                       idCardError:idResult.errorMessage];
}

#pragma mark - 辅助验证方法

- (BOOL)isValidChineseName:(NSString *)name {
    if (!name || name.length == 0) return NO;
    
    // 中文字符正则表达式
    NSString *chinesePattern = @"^[\\u4e00-\\u9fa5]+$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", chinesePattern];
    
    // 先检查是否全是中文字符
    if ([predicate evaluateWithObject:name]) {
        return YES;
    }
    
    // 支持中文+英文的复合姓名（如：李John，张Mary等）
    NSString *mixedPattern = @"^[\\u4e00-\\u9fa5]+[a-zA-Z]*$|^[a-zA-Z]+[\\u4e00-\\u9fa5]+$";
    NSPredicate *mixedPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", mixedPattern];
    
    return [mixedPredicate evaluateWithObject:name];
}

- (BOOL)isValidIDCardNumber:(NSString *)idCard {
    if (!idCard || idCard.length != 18) return NO;
    
    // 基本格式检查：前17位数字 + 最后一位数字或X
    NSString *pattern = @"^[0-9]{17}[0-9Xx]$";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];
    
    if (![predicate evaluateWithObject:idCard]) {
        return NO;
    }
    
    // 校验码检查
    return [self validateIDCardChecksum:idCard];
}

- (BOOL)validateIDCardChecksum:(NSString *)idCard {
    if (idCard.length != 18) return NO;
    
    // 加权因子
    NSArray *weightFactors = @[@7, @9, @10, @5, @8, @4, @2, @1, @6, @3, @7, @9, @10, @5, @8, @4, @2];
    
    // 校验码对应表
    NSArray *checksumChars = @[@"1", @"0", @"X", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
    
    int sum = 0;
    for (int i = 0; i < 17; i++) {
        NSString *digit = [idCard substringWithRange:NSMakeRange(i, 1)];
        int digitValue = [digit intValue];
        int weight = [weightFactors[i] intValue];
        sum += digitValue * weight;
    }
    
    int remainder = sum % 11;
    NSString *expectedChecksum = checksumChars[remainder];
    NSString *actualChecksum = [[idCard substringFromIndex:17] uppercaseString];
    
    return [expectedChecksum isEqualToString:actualChecksum];
}

- (NSString *)extractBirthdayFromIDCard:(NSString *)idCard {
    if (!idCard || idCard.length != 18) return nil;
    
    return [idCard substringWithRange:NSMakeRange(6, 8)];
}

- (BOOL)isTeenagerWithIDCard:(NSString *)idCard {
    NSString *birthday = [self extractBirthdayFromIDCard:idCard];
    if (!birthday || birthday.length != 8) return YES; // 默认为未成年
    
    NSInteger year = [[birthday substringToIndex:4] integerValue];
    NSInteger month = [[birthday substringWithRange:NSMakeRange(4, 2)] integerValue];
    NSInteger day = [[birthday substringFromIndex:6] integerValue];
    
    // 验证日期合法性
    if (year < 1900 || year > 2100 || month < 1 || month > 12 || day < 1 || day > 31) {
        return YES; // 日期不合法，默认为未成年
    }
    
    NSDateComponents *birthComponents = [[NSDateComponents alloc] init];
    birthComponents.year = year;
    birthComponents.month = month;
    birthComponents.day = day;
    
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *birthDate = [calendar dateFromComponents:birthComponents];
    if (!birthDate) return YES;
    
    NSDate *now = [NSDate date];
    NSDateComponents *ageComponents = [calendar components:NSCalendarUnitYear
                                                  fromDate:birthDate
                                                    toDate:now
                                                   options:0];
    
    return ageComponents.year < 18;
}

#pragma mark - 额外的验证方法

// 检查是否为测试身份证号
- (BOOL)isTestIDCard:(NSString *)idCard {
    NSArray *testIDs = @[
        @"110101199003078515", // 常见测试身份证
        @"000000000000000000",
        @"111111111111111111",
        @"123456789012345678"
    ];
    
    return [testIDs containsObject:idCard];
}

// 获取身份证所属地区
- (NSString *)getRegionFromIDCard:(NSString *)idCard {
    if (!idCard || idCard.length < 6) return @"未知地区";
    
    NSString *regionCode = [idCard substringToIndex:6];
    
    // 这里可以扩展完整的地区码映射表
    NSDictionary *regionMap = @{
        @"110000": @"北京市",
        @"120000": @"天津市",
        @"130000": @"河北省",
        @"140000": @"山西省",
        @"150000": @"内蒙古自治区",
        // ... 更多地区码
    };
    
    // 简化处理：只返回省级代码
    NSString *provinceCode = [[regionCode substringToIndex:2] stringByAppendingString:@"0000"];
    return regionMap[provinceCode] ?: @"未知地区";
}

@end
